<template>
  <zb-mask>
    <div class="zb-picker--datetime-wrapper">
      <div class="zb-picker--datetime__indicator">
        <div class="indicator__top"></div>
        <div class="indicator__main"></div>
        <div class="indicator__bottom"></div>
      </div>
      <div class="zb-picker--datetime__header">
        <span>取消</span>
        <span>{{getSelectTime}}</span>
        <span>确定</span>
      </div>
      <div class="zb-picker--datetime__content">
        <div class="picker--datetime-content__item datetime--years">
          <ul class="picker--datetime-content__item__box wheel-scroll">
            <li class="wheel-item" v-for="i in dateItem.yearsItem">{{i.name}}</li>
          </ul>
        </div>
        <div class="picker--datetime-content__item datetime--months">
          <ul class="picker--datetime-content__item__box wheel-scroll">
            <li class="wheel-item" v-for="i in dateItem.monthsItem">{{i.name}}</li>
          </ul>
        </div>
        <div class="picker--datetime-content__item datetime--days">
          <ul class="picker--datetime-content__item__box wheel-scroll">
            <li class="wheel-item" v-for="i in dateItem.daysItem">{{i.name}}</li>
          </ul>
        </div>
        <div class="picker--datetime-content__item datetime--hours">
          <ul class="picker--datetime-content__item__box wheel-scroll">
            <li class="wheel-item" v-for="i in dateItem.hoursItem">{{i.name}}</li>
          </ul>
        </div>
        <div class="picker--datetime-content__item datetime--mins">
          <ul class="picker--datetime-content__item__box wheel-scroll">
            <li class="wheel-item" v-for="i in dateItem.minsItem">{{i.name}}</li>
          </ul>
        </div>
      </div>
    </div>
  </zb-mask>
</template>

<script>
  import BScroll from 'better-scroll'
  import dateUtils from '@/utils/tools/DateUtils'

  export default {
    name: "ZbDatetimePicker",
    computed: {
      getSelectTime() {
        return this.selectItem.year.value + "-"
          + this.selectItem.month.value + "-"
          + this.selectItem.day.value + " "
          + this.selectItem.hour.value + ":"
          + this.selectItem.min.value;
      }
    },
    props: {
      DateType: {  // 要显示的时间类型 默认是yyyy-mm-dd
        default: 'yyyy-mm-dd hh:mm'
      },
      startTime: { // 开始时间
        required: false
      },
      endTime: { // 结束时间
        required: false
      }
    },
    data() {
      return {
        scrollParam: {
          scrollY: true,
          bounce: true,
          wheel: {
            selectedIndex: 0,
            rotate: 25,
            wheelWrapperClass: 'wheel-scroll',
            wheelItemClass: 'wheel-item'
          }
        },
        dateItem: {
          yearsItem: [],
          monthsItem: [],
          daysItem: [],
          hoursItem: [],
          minsItem: []
        },
        selectItem: {
          year: {
            value: 0,
            index: 0
          },
          month: {
            value: 0,
            index: 0
          },
          day: {
            value: 0,
            index: 0
          },
          hour: {
            value: 0,
            index: 0
          },
          min: {
            value: 0,
            index: 0
          },
        }
      }
    },
    mounted() {
      if (this.startTime && this.endTime) { //如果含有开始和结束时间
        this.dateItem.yearsItem = this.getYearsItems(this.startTime, this.endTime); //按照开始结束时间获取年份列表
        this.dateItem.monthsItem = this.getMonthItems(new Date(this.startTime).getFullYear(),
          this.startTime, this.endTime); //同上
        this.dateItem.daysItem = this.getDaysItems(new Date(this.startTime).getFullYear(),
          new Date(this.startTime).getMonth() + 1,
          this.startTime, this.endTime);  //同上
        this.dateItem.hoursItem = this.getHoursItems(new Date(this.startTime).getFullYear(),
          new Date(this.startTime).getMonth() + 1,
          new Date(this.startTime).getDate(),
          new Date(this.startTime).getHours(), 23,
          this.startTime, this.endTime);  //同上
        this.dateItem.minsItem = this.getMinsItems(new Date(this.startTime).getFullYear(),
          new Date(this.startTime).getMonth() + 1,
          new Date(this.startTime).getDate(),
          new Date(this.startTime).getHours(),
          this.startTime, this.endTime)  //同上
      } else { //如果不存在开始结束时间
        this.dateItem.yearsItem = this.getYearsItems(); //默认为空 获取当前日期前后100年的时间
        this.dateItem.monthsItem = this.getMonthItems(); //默认为空 获取当前日期前后100年的时间
        this.dateItem.daysItem = this.getDaysItems(); //默认为空 获取当前日期前后100年的时间
        this.dateItem.hoursItem = this.getHoursItems();  //默认为空 获取当前日期前后100年的时间
        this.dateItem.minsItem = this.getMinsItems(); //默认为空 获取当前日期前后100年的时间
      }

      this.$nextTick(() => { //data更新后
        //初始化当前选择项
        this.selectItem.year.value = this.dateItem.yearsItem[0].value; //获取时间列表第一个的value给默认值
        this.selectItem.year.index = 0;  //初始化日期选择列表的index为0

        this.selectItem.month.value = this.dateItem.monthsItem[0].value;
        this.selectItem.month.index = 0;

        this.selectItem.day.value = this.dateItem.daysItem[0].value;
        this.selectItem.day.index = 0;

        this.selectItem.hour.value = this.dateItem.hoursItem[0].value;
        this.selectItem.hour.index = 0;

        this.selectItem.min.value = this.dateItem.minsItem[0].value;
        this.selectItem.min.index = 0;

        this.initScroll();  //初始化scroll
      });
    },
    methods: {
      fixMonthDateBug() {
        if (!this.dateItem.monthsItem[this.selectItem.month.index]) {  // 如果当前选择的月份index没在当前的月份列表里
          /*
          * 这里要解释一下：这种情况说明当前选中的月份value和index都不在当前的月份列表内。
          * 例如：当前选择的是7.31，选中index就是32。如果切换到2月份，月份有28天，index最长29。
          * 就找不到32这个index。所以直接赋值2月份最后一天。
          * 这是月份的逻辑。其他同理还有“天”,“时”,“分”的同理逻辑。
          * 因为年是最大的单位，所以年不设置此逻辑
          * */
          this.selectItem.month.index = this.dateItem.monthsItem.length - 1;
          this.selectItem.month.value = this.dateItem.monthsItem[this.dateItem.monthsItem.length - 1].value
        } else { //如果在的话，只更新value值。
          this.selectItem.month.value = this.dateItem.monthsItem[this.selectItem.month.index].value
        }
      },
      fixDaysDateBug() {
        if (!this.dateItem.daysItem[this.selectItem.day.index]) {
          this.selectItem.day.index = this.dateItem.daysItem.length - 1;
          this.selectItem.day.value = this.dateItem.daysItem[this.dateItem.daysItem.length - 1].value
        } else {
          this.selectItem.day.value = this.dateItem.daysItem[this.selectItem.day.index].value
        }
      },
      fixHourDateBug() {
        if (!this.dateItem.hoursItem[this.selectItem.hour.index]) {
          this.selectItem.hour.index = this.dateItem.hoursItem.length - 1;
          this.selectItem.hour.value = this.dateItem.hoursItem[this.dateItem.hoursItem.length - 1].value
        } else {
          this.selectItem.hour.value = this.dateItem.hoursItem[this.selectItem.hour.index].value
        }
      },
      fixMinDateBug() {
        if (!this.dateItem.minsItem[this.selectItem.min.index]) {
          this.selectItem.min.index = this.dateItem.minsItem.length - 1;
          this.selectItem.min.value = this.dateItem.minsItem[this.dateItem.minsItem.length - 1].value
        } else {
          this.selectItem.min.value = this.dateItem.minsItem[this.selectItem.min.index].value
        }
      },
      initScroll() {
        let self = this; //新建变量重新指向this
        //年列表滚动
        let YearsScroll = new BScroll(document.getElementsByClassName("datetime--years")[0], this.scrollParam); //初始化scroll
        YearsScroll.on('scrollEnd', () => { //scrollEnd监听事件
          let selectYear = self.dateItem.yearsItem[YearsScroll.getSelectedIndex()].value; //获取当前选中的年份
          let selectMonth = self.dateItem.monthsItem[MonthsScroll.getSelectedIndex()].value; //获取当前选中的月份
          let selectDay = self.selectItem.day.value;  //获取当前选中的天
          self.selectItem.year.value = selectYear; //更新选中的年份
          self.selectItem.year.index = YearsScroll.getSelectedIndex();  //更新选中的年份
          if (self.startTime && self.endTime) {  //如果有开始结束日期
            if (new Date(self.startTime).getFullYear() === selectYear) { //如果开始年份===当前选择年份
              self.$nextTick(() => {
                // 重新刷新月份列表 传入开始日期的年份，开始的时间和结束时间
                self.dateItem.monthsItem = self.getMonthItems(new Date(self.startTime).getFullYear(), self.startTime, self.endTime);
                // 更新当前选中月份
                self.fixMonthDateBug();
              });
              self.$nextTick(() => {
                // 重新刷新天份列表 传入开始日期的年份,开始时间的月份，开始的时间和结束时间
                self.dateItem.daysItem = self.getDaysItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  self.startTime, self.endTime);
                // 更新当前选中天
                self.fixDaysDateBug();
              });
              self.$nextTick(() => {
                // 重新刷新时列表 传入开始日期的年份,开始时间的月份,开始时间的天份，开始时刻-23时。
                self.dateItem.hoursItem = self.getHoursItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), 23);
                // 更新当前选中时
                self.fixHourDateBug();
              });
              self.$nextTick(() => {
                // 重新刷新分列表 传入开始日期的年份,开始时间的月份,开始时间的天份，开始时刻，开始的时间和结束时间
                self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), self.startTime, self.endTime);
                // 更新当前选中分
                self.fixMinDateBug();
              });
              return false;
            } else if (new Date(self.endTime).getFullYear() === selectYear) { //如果是结束时间 与开始时间同理
              // 您选中了最后一个年份
              self.dateItem.monthsItem = self.getMonthItems(
                new Date(self.endTime).getFullYear(),
                self.startTime, self.endTime);
              self.$nextTick(() => {
                self.fixMonthDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.daysItem = self.getDaysItems(
                  new Date(self.endTime).getFullYear(),
                  self.startTime, self.endTime);
                self.fixDaysDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.hoursItem = self.getHoursItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  0, new Date(self.endTime).getHours()); //因为是结束时间，所以时刻要从0-结束时间
                self.fixHourDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  new Date(self.endTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            }
          }
          //如果没有传入开始和结束时间
          self.dateItem.monthsItem = self.getMonthItems(selectYear, null, null); //根据当前选中的年份，更新月份列表
          self.$nextTick(() => {
            // 更新当前选中月份
            self.fixMonthDateBug();
          });
          self.$nextTick(() => {
            //根据当前选中的年份和月份，更新天份列表
            self.dateItem.daysItem = self.getDaysItems(selectYear, this.selectItem.month.value, null, null);
            self.fixDaysDateBug();
          });
          self.$nextTick(() => {
            // 简单粗暴 0-23时
            self.dateItem.hoursItem = self.getHoursItems(null, null, null, 0, 23);
            self.fixHourDateBug();
          });
          self.$nextTick(() => {
            //根据当前选中的年份，月份，天，更新分份列表
            self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);
            self.fixMinDateBug();
          });
          return false;
        });

        //月列表滚动
        let MonthsScroll = new BScroll(document.getElementsByClassName("datetime--months")[0], this.scrollParam);
        MonthsScroll.on('scrollEnd', () => {
          let selectYear = self.dateItem.yearsItem[YearsScroll.getSelectedIndex()].value;
          //选中的月份Value
          let selectMonth = self.dateItem.monthsItem[MonthsScroll.getSelectedIndex()].value;
          let selectDay = self.selectItem.day.value;
          self.selectItem.month.value = selectMonth;
          self.selectItem.month.index = MonthsScroll.getSelectedIndex();

          if (self.startTime && self.endTime) {
            if (MonthsScroll.getSelectedIndex() === 0 && new Date(self.startTime).getFullYear() === parseInt(selectYear)) {
              self.$nextTick(() => {
                self.dateItem.daysItem = self.getDaysItems(new Date(self.startTime).getFullYear(), new Date(self.startTime).getMonth() + 1, self.startTime, self.endTime);
                self.fixDaysDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.hoursItem = self.getHoursItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), 23);
                self.fixHourDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            } else if (new Date(self.endTime).getMonth() + 1 === parseInt(selectMonth) && new Date(self.endTime).getFullYear() === parseInt(selectYear)) {
              self.$nextTick(() => {
                self.dateItem.daysItem = self.getDaysItems(new Date(self.endTime).getFullYear(), new Date(self.endTime).getMonth() + 1, self.startTime, self.endTime);
                self.fixDaysDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.hoursItem = self.getHoursItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  0, new Date(self.endTime).getHours());
                self.fixHourDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  new Date(self.endTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            }
          }
          self.$nextTick(() => {
            self.dateItem.daysItem = self.getDaysItems(selectYear, selectMonth, null, null);
            self.fixDaysDateBug();
          });
          self.$nextTick(() => {
            self.dateItem.hoursItem = self.getHoursItems(null, null, null, 0, 24);
            self.fixHourDateBug();
          });
          self.$nextTick(() => {
            self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);
            self.fixMinDateBug();
          });
          return false;
        });

        //日列表滚动
        let DaysScroll = new BScroll(document.getElementsByClassName("datetime--days")[0], this.scrollParam);
        DaysScroll.on('scrollEnd', () => {
          self.selectItem.day.value = self.dateItem.daysItem[DaysScroll.getSelectedIndex()].value;
          self.selectItem.day.index = DaysScroll.getSelectedIndex();
          let selectYear = self.selectItem.year.value;
          let selectMonth = self.selectItem.month.value;
          let selectDay = self.selectItem.day.value;
          if (self.startTime && self.endTime) {
            if (new Date(self.startTime).getFullYear() === parseInt(selectYear)
              && new Date(self.startTime).getMonth() + 1 === parseInt(selectMonth)
              && new Date(self.startTime).getDate() === parseInt(selectDay)) {
              self.$nextTick(() => {
                self.dateItem.hoursItem = self.getHoursItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), 23);
                self.fixHourDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            } else if (new Date(self.endTime).getFullYear() === parseInt(selectYear)
              && new Date(self.endTime).getMonth() + 1 === parseInt(selectMonth)
              && new Date(self.endTime).getDate() === parseInt(selectDay)) {
              self.$nextTick(() => {
                self.dateItem.hoursItem = self.getHoursItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  0, new Date(self.endTime).getHours());
                self.fixHourDateBug();
              });
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  new Date(self.endTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            }
          }
          self.dateItem.hoursItem = self.getHoursItems(null, null, null, 0, 24);
          self.$nextTick(() => {
            self.fixHourDateBug();
          });
          self.$nextTick(() => {
            self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);
            self.fixMinDateBug();
          });
          return false;
        })

        //时列表滚动
        let HoursScroll = new BScroll(document.getElementsByClassName("datetime--hours")[0], this.scrollParam);
        HoursScroll.on('scrollEnd', () => {
          self.selectItem.hour.value = self.dateItem.hoursItem[HoursScroll.getSelectedIndex()].value;
          self.selectItem.hour.index = HoursScroll.getSelectedIndex();
          let selectYear = self.selectItem.year.value;
          let selectMonth = self.selectItem.month.value;
          let selectDay = self.selectItem.day.value;
          let selectHour = self.selectItem.hour.value;
          if (self.startTime && self.endTime) {
            if (new Date(self.startTime).getFullYear() === parseInt(selectYear)
              && new Date(self.startTime).getMonth() + 1 === parseInt(selectMonth)
              && new Date(self.startTime).getDate() === parseInt(selectDay)
              && new Date(self.startTime).getHours() === parseInt(selectHour)) {
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.startTime).getFullYear(),
                  new Date(self.startTime).getMonth() + 1,
                  new Date(self.startTime).getDate(),
                  new Date(self.startTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            } else if (new Date(self.endTime).getFullYear() === parseInt(selectYear)
              && new Date(self.endTime).getMonth() + 1 === parseInt(selectMonth)
              && new Date(self.endTime).getDate() === parseInt(selectDay)
              && new Date(self.endTime).getHours() === parseInt(selectHour)) {
              self.$nextTick(() => {
                self.dateItem.minsItem = self.getMinsItems(new Date(self.endTime).getFullYear(),
                  new Date(self.endTime).getMonth() + 1,
                  new Date(self.endTime).getDate(),
                  new Date(self.endTime).getHours(), self.startTime, self.endTime);
                self.fixMinDateBug();
              });
              return false;
            }
          }
          self.$nextTick(() => {
            self.dateItem.minsItem = self.getMinsItems(selectYear, selectMonth, selectDay, null, null);
            self.fixMinDateBug();
          });
          return false;
        })

        //分列表滚动
        let MinsScroll = new BScroll(document.getElementsByClassName("datetime--mins")[0], this.scrollParam);
        MinsScroll.on('scrollEnd', () => {
          self.selectItem.min.value = self.dateItem.minsItem[MinsScroll.getSelectedIndex()].value;
          self.selectItem.min.index = MinsScroll.getSelectedIndex();
        })
      },
      getYearsItems(startDate, endDate) {
        return dateUtils.getYearItems({
          format: '{value}年',
          startDate: startDate ? startDate : '',
          endDate: endDate ? endDate : ''
        })
      },
      getMonthItems(currentYear, startDate, endDate) {
        return dateUtils.getMonthItems({
          format: '{value}月',
          startDate: startDate ? startDate : '',
          endDate: endDate ? endDate : '',
          currentYear: currentYear ? currentYear : ''
        })
      },
      getDaysItems(currentYear, currentMonth, startDate, endDate) {
        return dateUtils.getDayItems({
          format: '{value}日',
          startDate: startDate ? startDate : '',
          endDate: endDate ? endDate : '',
          currentYear: currentYear ? currentYear : '',
          currentMonth: currentMonth ? currentMonth : '',
        })
      },
      getHoursItems(currentYear, currentMonth, currentDay, startHour, endHour, startDate, endDate) {
        return dateUtils.getHourItems({
          format: '{value}时',
          startDate: startDate ? startDate : '',
          endDate: endDate ? endDate : '',
          currentYear: currentYear ? currentYear : '',
          currentMonth: currentMonth ? currentMonth : '',
          currentDay: currentDay ? currentDay : '',
          startHour: startHour ? startHour : 0,
          endHour: endHour ? endHour : 23
        })
      },
      getMinsItems(currentYear, currentMonth, currentDay, currentHour, startDate, endDate) {
        return dateUtils.getMinuteItems({
          format: '{value}分',
          startDate: startDate ? startDate : '',
          endDate: endDate ? endDate : '',
          currentYear: currentYear ? currentYear : '',
          currentMonth: currentMonth ? currentMonth : '',
          currentDay: currentDay ? currentDay : '',
          currentHour: currentHour ? currentHour : '',
        })
      },
    }
  }
</script>

<style scoped>
  * {
    color: black;
  }

  .zb-picker--datetime-wrapper {
    transition: transform .25s, -webkit-transform .25s;
    touch-action: none;
    will-change: transform;
    z-index: 1600;
    position: fixed;
    bottom: 0;
    background-color: white;
    width: 100%;
  }

  .zb-picker--datetime__header {
    display: flex;
    justify-content: space-between;
    position: relative;
  }

  .zb-picker--datetime__header > span {
    align-items: center;
    padding: 1rem 2.6rem;
    font-size: 1.5rem;
    cursor: pointer;
    user-select: none;
  }

  .zb-picker--datetime__header > span:last-child {
    color: #1890FF;
  }

  .zb-picker--datetime__content {
    height: 22rem;
    display: flex;
    flex-direction: row;
  }

  .picker--datetime-content__item {
    flex: 1;
    text-align: center;
    overflow: hidden;
  }

  .picker--datetime-content__item > .picker--datetime-content__item__box {
    display: flex;
    flex-direction: column;
    margin-top: 9rem;
  }

  .picker--datetime-content__item__box > li {
    height: 3rem;
    line-height: 3rem;
    font-size: 1.3rem;
    user-select: none;
  }

  .zb-picker--datetime__indicator {
    position: absolute;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    padding-top: 4rem;
  }

  .zb-picker--datetime__indicator .indicator__main {
    position: relative;
    /*border: 1px solid #ECECEC;*/
    border-right-width: 0;
    border-left-width: 0;
    flex: 1;
  }

  .indicator__top {
    z-index: 1600;
    pointer-events: none;
    flex: 4;
    background: linear-gradient(0deg, hsla(0, 0%, 100%, .4), hsla(0, 0%, 100%, .8));
  }

  .indicator__bottom {
    z-index: 1600;
    pointer-events: none;
    flex: 6;
    background: linear-gradient(0deg, hsla(0, 0%, 100%, .4), hsla(0, 0%, 100%, .8));
  }
</style>
